package ynu.edu.order.listener;

import com.rabbitmq.client.Channel;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;
import ynu.edu.api.client.PayClient;
import ynu.edu.api.dto.PayOrderDTO;
import ynu.edu.order.constans.MQConstants;
import ynu.edu.order.domain.po.Order;
import ynu.edu.order.service.IOrderService;

import java.io.IOException;

@Slf4j
@Component
@RequiredArgsConstructor
public class OrderDelayListener {

    private final IOrderService orderService;
    private final PayClient payClient;
    private final RabbitTemplate rabbitTemplate;

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = MQConstants.DELAY_ORDER_QUEUE_NAME, durable = "true"),
            exchange = @Exchange(name = MQConstants.DELAY_EXCHANGE_NAME),
            key = MQConstants.DELAY_ORDER_KEY
    ))
    public void ListenOrderDelayMessage(String message, Channel channel,
                                        @Header(AmqpHeaders.DELIVERY_TAG) long tag,
                                        @Header(name = "x-retry-count", required = false) Integer retry) {
        Long orderId = Long.parseLong(message);
        log.info("[OrderDelayListener] 收到延迟消息，订单ID: {}", orderId);

        int count = retry == null ? 0 : retry;          // 当前已重试次数
        final int MAX = 3;                              // 最多再查 3 次（共 15+5*3=30 min）

        try {
            // 1.查询订单
            Order order = orderService.getById(orderId);
            if (order == null) {
                log.warn("[OrderDelayListener] 订单{}不存在，跳过处理", orderId);
                handleAck(channel, tag);
                return;
            }
            
            // 2.检测订单状态，判断是否已支付
            if (order.getStatus() != 1) {
                log.info("[OrderDelayListener] 订单{}状态为{}，已不是未支付状态，跳过处理", 
                        orderId, order.getStatus());
                handleAck(channel, tag);
                return;
            }
            
            // 3.未支付，需要查询支付流水状态
            log.info("[OrderDelayListener] 订单{}未支付，开始查询支付状态", orderId);
            PayOrderDTO payOrder = payClient.queryPayOrderByBizOrderNo(orderId);
            
            // 4.判断是否支付
            if (payOrder != null && payOrder.getStatus() == 3) {
                // 4.1.已支付，标记订单状态为已支付
                log.info("[OrderDelayListener] 订单{}已支付，更新订单状态", orderId);
                orderService.markOrderPaySuccess(orderId);
                handleAck(channel, tag);
            }
            // 4.2. 未查到流水
            if (count < MAX) {
                log.info("订单{}未查到支付流水，第{}次重试", orderId, count + 1);
                // 重新投递：5 min 后再查
                rabbitTemplate.convertAndSend(
                        MQConstants.DELAY_EXCHANGE_NAME,
                        MQConstants.DELAY_ORDER_KEY,
                        String.valueOf(orderId),
                        msg -> {
                            msg.getMessageProperties().setDelay(5 * 60 * 1000); // 5 min
                            msg.getMessageProperties().setHeader("x-retry-count", count + 1);
                            return msg;
                        });
            } else {
                log.info("订单{}已达最大重试次数，关闭订单", orderId);
                orderService.cancelOrder(orderId);
            }
            handleAck(channel, tag);
        } catch (Exception e) {
            log.error("[OrderDelayListener] 处理延迟消息失败，订单ID: {}", orderId, e);
            // 延迟消息处理失败不需要重试，直接记录日志即可
            // 可以考虑发送告警通知或记录到专门的错误日志表
            handleAck(channel, tag);
        }
    }

    // 统一处理消息确认（Ack）
    private void handleAck(Channel channel, long tag) {
        try {
            if (channel.isOpen()) {
                channel.basicAck(tag, false);
                log.debug("[OrderDelayListener] 消息确认成功, tag: {}", tag);
            } else {
                log.warn("[OrderDelayListener] 通道已关闭，无法确认消息, tag: {}", tag);
            }
        } catch (IOException e) {
            log.error("[OrderDelayListener] 确认消息失败, tag: {}", tag, e);
        }
    }

    // 统一处理消息拒绝（Nack）
    private void handleNack(Channel channel, long tag, boolean requeue) {
        try {
            if (channel.isOpen()) {
                channel.basicNack(tag, false, requeue);
                log.debug("[OrderDelayListener] 消息拒绝成功, tag: {}, requeue: {}", tag, requeue);
            } else {
                log.warn("[OrderDelayListener] 通道已关闭，无法拒绝消息, tag: {}", tag);
            }
        } catch (IOException e) {
            log.error("[OrderDelayListener] 拒绝消息失败, tag: {}", tag, e);
        }
    }
}
